主にLLVMを使用しています
概要
http://partake.in/events/9658f376-6ce3-4217-b392-b05d3de60021
昨日は @yusuke_kokubo さんでした。
りあじゅうばくはつしろ!
で
LLとかMLという語句がついてればOKだと思うので、
今回は
_人人人人人人人人人人_
> 突然のemscripten <
 ̄^Y^Y^Y^Y^Y^Y^Y^Y^ ̄
emscriptenとは
OCamlでJSやるのとかありますよね。 いいですよね!! JS書かずにすむとかGooooodです。
emscriptenは、
その辺の「こんな言語からJSが生成されるなんて!!」的な言語のお友達です。
こわくない。
Q.どこがMLだったりLLなのか
A.LLVMです。 JS生成にLLVMを使用しています。
emscriptenは、LLVMを使って、いろんな言語のコンパイル結果としてJSを吐き出します。
毎回なぜかこの辺でドン引きされますが、
コワくない。
本体
githubにホストして開発されてる
https://github.com/kripken/emscripten/wiki
わかりやすい日本語での解説
Emscriptenの論文読んだ。Webの賢い選択。
http://akidev.hateblo.jp/entry/2012/04/12/233934
自分も5月くらいになんか書いてました。もう古い。
emscriptenを動かしてみる
http://sassembla.github.com/Public/12:05:21%2017-38-30/12:05:21%2017-38-30.html
補足
LLVMって?
コレ。 コンパイラみたいなものです。
やってみよう!
今回は、Objective-CのコードをJS化してみるよ!
といってもヘビー級だと絶対破滅するので、
軽めのをソースからJS化してみます。
脱線するけど。
本来の「言語をコンパイル可能な状況に持ち込む事で、出来るとうれしい事は何か」;
1.メッセージングの機構とか、JSでやるとクソみたいな事を、Cとかで書いてJSに持ち込む
2.人の手が絶対につけられないJSソースコードを吐く(マイナーチェンジや場当たりなど、変更可能性の更迭)
3.テストが容易
2.3が絶大なメリットだと思ってて、
変更可能性の無い = 人間が弄れない、なんだけど、
そういうソースコードでなにかをコントロールする世界にしていかないと、Webまわりはもうずっとこのままだと思う。
外部化のために、変更可能性をより上部に持っていく必要を感じているのです。
で、手順!
MacでClangをインストール
Xcodeから入れると、フレームワークとかのパス設定をはしょれて凄く楽です。
Xcode > Preferences > Downloads >
最初llvm自体をDLして、ガチで挑んで死ぬかと思いました。
Windowsでも調べてみたら相ッ当なドMな方だとお見受けしますが、
何人か「環境作ってみたぜ!」な方々がいらっしゃいました。正直koeee。
Cの簡単なファイルを試しに一発ビルド
対象のファイルはこんな感じ。
test.c
#include <stdio.h>
int main()
{
int i = 0;
for (i = 0; i < 99; i++) printf("hello, world %d\n", i);
return 0;
}
適当な回数hello, world っていうプログラムです。
ビルド
llvmは、clangというフロントエンドツールを介してコントロールします。
ビルドコマンドは
clang test.c -v
↓
成果としてa.outができましたよっと。
Obj-Cの簡単なファイルを試しに一発ビルド
対象のファイルはこんな感じ
test.m
#import <Foundation/Foundation.h>
@interface X : NSObject
@end
@implementation X
-(void)hello {
printf("Hello\n");
}
@end
int main() {
X * obj = [[X alloc] init];
[obj hello];
return 0;
}
ビルド
clang -fobjc-arc -framework Foundation test.m -o testObjC.out
↓
出来上がったバイナリを実行すると、
ビルドできる環境が整ったら、.ll/.bcファイルを出力
emscriptenに喰わせるため、LLVM IR(Intermediate Representation) = LLVM上でのコード中間表現 を生成する。
ちょっと脱線しつつ説明しておくと、
llvmは「ローレベルなバーチャルマシンで色んな事をする為のコンパイルの基盤」で、
その目的は
・言語をビルドする行為それ自体と、ビルドしたものが実際に動作するアーキテクチャを切り離す
・中間言語の時点で最適化を施す
というもの。超ザックリ。
で、.ll/.bcファイルは、その中間言語化された状態。optとかを使って最適化ができる。ここではやんないけど。
実行形式を引きずってない、意図だけのソース。
その辺をclangからつくる。
clang -O3 -emit-llvm test.m -c -o test.bc
こんなのが出来る。
emscriptenのセットアップ
割愛。
参考になるステキな記事。
c/c++ -> javascript 変換compiler - emscripten を試す
http://d.hatena.ne.jp/end0tknr/20120714/1342233561
作成した中間言語をemsriptenでjs化
C言語版
./emscripten/emcc ソース.c
出力されるのが、.jsファイル。
-o 出力ファイル名 とかで調整も可能。
Cオリジナル
https://dl.dropbox.com/u/36583594/shared/test/test.c
js化したものをhtmlに入れたヤツ
https://dl.dropbox.com/u/36583594/shared/test/test.html
Cのprintfに対応して、プリント文が出てるぞ!! デバッガを見てね!
Obj-C版
オリジナル
https://dl.dropbox.com/u/36583594/shared/test/test.m
★最新のemsだと、.llからの変換が駄目らしい!!!
調整中、、2012/12/18 23:57:43
明日は @kei10in さんです。
番外編:失敗狂の詩
何手か、悪手っぽいものを試して失敗したのでメモまでに。
Obj-Cからc++とかに変換すればいいんじゃね?
clang -rewrite-objc で.mファイルをcppファイルに変換できるので、それをビルドすれば、、!!という。
アイデア自体はまあ平和だったんですが、詰まったので方向転換しました。
以下メモ
emscripten側を弄る
・設定ファイルを更新
LLVM_ROOT = os.path.expanduser(os.getenv('LLVM') or '/usr/bin/')
llvm-linkとllvm-arとoptとllvm-asとllvm-disと
llvm-nmを追加
で、
./emscripten/emcc /Users/sassembla/test/ems/test.m.cpp
(Emscripten: settings file has changed, clearing cache)
warning: LLVM version appears incorrect (seeing "Apple clang version 4.1 (tags/Apple/clang-421.11.66) (based on LLVM 3.1svn)", expected "clang version 3.1")
(Emscripten: Running sanity checks)
/Users/sassembla/test/ems/test.m.cpp:69:9: warning: '__block' macro redefined
#define __block
^
<built-in>:20:9: note: previous definition is here
#define __block __attribute__((__blocks__(byref)))
^
/Users/sassembla/test/ems/test.m.cpp:73:10: fatal error:
'Foundation/Foundation.h' file not found
#include <Foundation/Foundation.h>
^
1 warning and 1 error generated.
emcc: compiler frontend failed to generate LLVM bitcode, halting
なので、
frameworkを読むように設定して、
./emscripten/emcc -framework /System/Library/Frameworks/Foundation.framework/Headers/Foundation.h /Users/sassembla/test/ems/test.m.cpp -o a.out.js
おおーエラー無く出せた。
でもこれ何が出てるんだろう。。。
↓
CPPがそのまま吐かれてた
グハー
ということで、このルートは無し。
再度チャレンジ
./emscripten/emcc -framework /Users/sassembla/test/ems/test.m.cpp -o a.out.js
llvmが吐き出す中間成果物をもとに、emscriptenしてみる
llvm-dis
llvm-dis /Users/sassembla/Desktop/compile/test.bc